/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.s2aei.model.dao;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import com.s2aei.model.Status;
import com.s2aei.model.Papeis;
import com.s2aei.model.Professor;
import java.util.ArrayList;
import java.util.List;
import com.s2aei.model.Avaliador;
import com.s2aei.model.Aluno;
import com.s2aei.model.Usuario;
import com.s2aei.model.UsuarioPK;
import com.s2aei.model.dao.exceptions.IllegalOrphanException;
import com.s2aei.model.dao.exceptions.NonexistentEntityException;
import com.s2aei.model.dao.exceptions.PreexistingEntityException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 *
 * @author Christian
 */
public class UsuarioDAO implements Serializable {

    public UsuarioDAO() {
        this.emf = Persistence.createEntityManagerFactory("S2AEILibPU");;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Usuario usuario) throws PreexistingEntityException, Exception {
        if (usuario.getUsuarioPK() == null) {
            usuario.setUsuarioPK(new UsuarioPK());
        }
        if (usuario.getProfessorList() == null) {
            usuario.setProfessorList(new ArrayList<Professor>());
        }
        if (usuario.getAvaliadorList() == null) {
            usuario.setAvaliadorList(new ArrayList<Avaliador>());
        }
        if (usuario.getAlunoList() == null) {
            usuario.setAlunoList(new ArrayList<Aluno>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Status status = usuario.getStatus();
            if (status != null) {
                status = em.getReference(status.getClass(), status.getTipo());
                usuario.setStatus(status);
            }
            Papeis papel = usuario.getPapel();
            if (papel != null) {
                papel = em.getReference(papel.getClass(), papel.getTipo());
                usuario.setPapel(papel);
            }
            List<Professor> attachedProfessorList = new ArrayList<Professor>();
            for (Professor professorListProfessorToAttach : usuario.getProfessorList()) {
                professorListProfessorToAttach = em.getReference(professorListProfessorToAttach.getClass(), professorListProfessorToAttach.getProfessorPK());
                attachedProfessorList.add(professorListProfessorToAttach);
            }
            usuario.setProfessorList(attachedProfessorList);
            List<Avaliador> attachedAvaliadorList = new ArrayList<Avaliador>();
            for (Avaliador avaliadorListAvaliadorToAttach : usuario.getAvaliadorList()) {
                avaliadorListAvaliadorToAttach = em.getReference(avaliadorListAvaliadorToAttach.getClass(), avaliadorListAvaliadorToAttach.getAvaliadorPK());
                attachedAvaliadorList.add(avaliadorListAvaliadorToAttach);
            }
            usuario.setAvaliadorList(attachedAvaliadorList);
            List<Aluno> attachedAlunoList = new ArrayList<Aluno>();
            for (Aluno alunoListAlunoToAttach : usuario.getAlunoList()) {
                alunoListAlunoToAttach = em.getReference(alunoListAlunoToAttach.getClass(), alunoListAlunoToAttach.getAlunoPK());
                attachedAlunoList.add(alunoListAlunoToAttach);
            }
            usuario.setAlunoList(attachedAlunoList);
            em.persist(usuario);
            if (status != null) {
                status.getUsuarioList().add(usuario);
                status = em.merge(status);
            }
            if (papel != null) {
                papel.getUsuarioList().add(usuario);
                papel = em.merge(papel);
            }
            for (Professor professorListProfessor : usuario.getProfessorList()) {
                Usuario oldUsuarioOfProfessorListProfessor = professorListProfessor.getUsuario();
                professorListProfessor.setUsuario(usuario);
                professorListProfessor = em.merge(professorListProfessor);
                if (oldUsuarioOfProfessorListProfessor != null) {
                    oldUsuarioOfProfessorListProfessor.getProfessorList().remove(professorListProfessor);
                    oldUsuarioOfProfessorListProfessor = em.merge(oldUsuarioOfProfessorListProfessor);
                }
            }
            for (Avaliador avaliadorListAvaliador : usuario.getAvaliadorList()) {
                Usuario oldUsuarioOfAvaliadorListAvaliador = avaliadorListAvaliador.getUsuario();
                avaliadorListAvaliador.setUsuario(usuario);
                avaliadorListAvaliador = em.merge(avaliadorListAvaliador);
                if (oldUsuarioOfAvaliadorListAvaliador != null) {
                    oldUsuarioOfAvaliadorListAvaliador.getAvaliadorList().remove(avaliadorListAvaliador);
                    oldUsuarioOfAvaliadorListAvaliador = em.merge(oldUsuarioOfAvaliadorListAvaliador);
                }
            }
            for (Aluno alunoListAluno : usuario.getAlunoList()) {
                Usuario oldUsuarioOfAlunoListAluno = alunoListAluno.getUsuario();
                alunoListAluno.setUsuario(usuario);
                alunoListAluno = em.merge(alunoListAluno);
                if (oldUsuarioOfAlunoListAluno != null) {
                    oldUsuarioOfAlunoListAluno.getAlunoList().remove(alunoListAluno);
                    oldUsuarioOfAlunoListAluno = em.merge(oldUsuarioOfAlunoListAluno);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findUsuario(usuario.getUsuarioPK()) != null) {
                throw new PreexistingEntityException("Usuario " + usuario + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Usuario usuario) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario persistentUsuario = em.find(Usuario.class, usuario.getUsuarioPK());
            Status statusOld = persistentUsuario.getStatus();
            Status statusNew = usuario.getStatus();
            Papeis papelOld = persistentUsuario.getPapel();
            Papeis papelNew = usuario.getPapel();
            List<Professor> professorListOld = persistentUsuario.getProfessorList();
            List<Professor> professorListNew = usuario.getProfessorList();
            List<Avaliador> avaliadorListOld = persistentUsuario.getAvaliadorList();
            List<Avaliador> avaliadorListNew = usuario.getAvaliadorList();
            List<Aluno> alunoListOld = persistentUsuario.getAlunoList();
            List<Aluno> alunoListNew = usuario.getAlunoList();
            List<String> illegalOrphanMessages = null;
            for (Professor professorListOldProfessor : professorListOld) {
                if (!professorListNew.contains(professorListOldProfessor)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Professor " + professorListOldProfessor + " since its usuario field is not nullable.");
                }
            }
            for (Avaliador avaliadorListOldAvaliador : avaliadorListOld) {
                if (!avaliadorListNew.contains(avaliadorListOldAvaliador)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Avaliador " + avaliadorListOldAvaliador + " since its usuario field is not nullable.");
                }
            }
            for (Aluno alunoListOldAluno : alunoListOld) {
                if (!alunoListNew.contains(alunoListOldAluno)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Aluno " + alunoListOldAluno + " since its usuario field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (statusNew != null) {
                statusNew = em.getReference(statusNew.getClass(), statusNew.getTipo());
                usuario.setStatus(statusNew);
            }
            if (papelNew != null) {
                papelNew = em.getReference(papelNew.getClass(), papelNew.getTipo());
                usuario.setPapel(papelNew);
            }
            List<Professor> attachedProfessorListNew = new ArrayList<Professor>();
            for (Professor professorListNewProfessorToAttach : professorListNew) {
                professorListNewProfessorToAttach = em.getReference(professorListNewProfessorToAttach.getClass(), professorListNewProfessorToAttach.getProfessorPK());
                attachedProfessorListNew.add(professorListNewProfessorToAttach);
            }
            professorListNew = attachedProfessorListNew;
            usuario.setProfessorList(professorListNew);
            List<Avaliador> attachedAvaliadorListNew = new ArrayList<Avaliador>();
            for (Avaliador avaliadorListNewAvaliadorToAttach : avaliadorListNew) {
                avaliadorListNewAvaliadorToAttach = em.getReference(avaliadorListNewAvaliadorToAttach.getClass(), avaliadorListNewAvaliadorToAttach.getAvaliadorPK());
                attachedAvaliadorListNew.add(avaliadorListNewAvaliadorToAttach);
            }
            avaliadorListNew = attachedAvaliadorListNew;
            usuario.setAvaliadorList(avaliadorListNew);
            List<Aluno> attachedAlunoListNew = new ArrayList<Aluno>();
            for (Aluno alunoListNewAlunoToAttach : alunoListNew) {
                alunoListNewAlunoToAttach = em.getReference(alunoListNewAlunoToAttach.getClass(), alunoListNewAlunoToAttach.getAlunoPK());
                attachedAlunoListNew.add(alunoListNewAlunoToAttach);
            }
            alunoListNew = attachedAlunoListNew;
            usuario.setAlunoList(alunoListNew);
            usuario = em.merge(usuario);
            if (statusOld != null && !statusOld.equals(statusNew)) {
                statusOld.getUsuarioList().remove(usuario);
                statusOld = em.merge(statusOld);
            }
            if (statusNew != null && !statusNew.equals(statusOld)) {
                statusNew.getUsuarioList().add(usuario);
                statusNew = em.merge(statusNew);
            }
            if (papelOld != null && !papelOld.equals(papelNew)) {
                papelOld.getUsuarioList().remove(usuario);
                papelOld = em.merge(papelOld);
            }
            if (papelNew != null && !papelNew.equals(papelOld)) {
                papelNew.getUsuarioList().add(usuario);
                papelNew = em.merge(papelNew);
            }
            for (Professor professorListNewProfessor : professorListNew) {
                if (!professorListOld.contains(professorListNewProfessor)) {
                    Usuario oldUsuarioOfProfessorListNewProfessor = professorListNewProfessor.getUsuario();
                    professorListNewProfessor.setUsuario(usuario);
                    professorListNewProfessor = em.merge(professorListNewProfessor);
                    if (oldUsuarioOfProfessorListNewProfessor != null && !oldUsuarioOfProfessorListNewProfessor.equals(usuario)) {
                        oldUsuarioOfProfessorListNewProfessor.getProfessorList().remove(professorListNewProfessor);
                        oldUsuarioOfProfessorListNewProfessor = em.merge(oldUsuarioOfProfessorListNewProfessor);
                    }
                }
            }
            for (Avaliador avaliadorListNewAvaliador : avaliadorListNew) {
                if (!avaliadorListOld.contains(avaliadorListNewAvaliador)) {
                    Usuario oldUsuarioOfAvaliadorListNewAvaliador = avaliadorListNewAvaliador.getUsuario();
                    avaliadorListNewAvaliador.setUsuario(usuario);
                    avaliadorListNewAvaliador = em.merge(avaliadorListNewAvaliador);
                    if (oldUsuarioOfAvaliadorListNewAvaliador != null && !oldUsuarioOfAvaliadorListNewAvaliador.equals(usuario)) {
                        oldUsuarioOfAvaliadorListNewAvaliador.getAvaliadorList().remove(avaliadorListNewAvaliador);
                        oldUsuarioOfAvaliadorListNewAvaliador = em.merge(oldUsuarioOfAvaliadorListNewAvaliador);
                    }
                }
            }
            for (Aluno alunoListNewAluno : alunoListNew) {
                if (!alunoListOld.contains(alunoListNewAluno)) {
                    Usuario oldUsuarioOfAlunoListNewAluno = alunoListNewAluno.getUsuario();
                    alunoListNewAluno.setUsuario(usuario);
                    alunoListNewAluno = em.merge(alunoListNewAluno);
                    if (oldUsuarioOfAlunoListNewAluno != null && !oldUsuarioOfAlunoListNewAluno.equals(usuario)) {
                        oldUsuarioOfAlunoListNewAluno.getAlunoList().remove(alunoListNewAluno);
                        oldUsuarioOfAlunoListNewAluno = em.merge(oldUsuarioOfAlunoListNewAluno);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                UsuarioPK id = usuario.getUsuarioPK();
                if (findUsuario(id) == null) {
                    throw new NonexistentEntityException("The usuario with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(UsuarioPK id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario usuario;
            try {
                usuario = em.getReference(Usuario.class, id);
                usuario.getUsuarioPK();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The usuario with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Professor> professorListOrphanCheck = usuario.getProfessorList();
            for (Professor professorListOrphanCheckProfessor : professorListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Professor " + professorListOrphanCheckProfessor + " in its professorList field has a non-nullable usuario field.");
            }
            List<Avaliador> avaliadorListOrphanCheck = usuario.getAvaliadorList();
            for (Avaliador avaliadorListOrphanCheckAvaliador : avaliadorListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Avaliador " + avaliadorListOrphanCheckAvaliador + " in its avaliadorList field has a non-nullable usuario field.");
            }
            List<Aluno> alunoListOrphanCheck = usuario.getAlunoList();
            for (Aluno alunoListOrphanCheckAluno : alunoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Usuario (" + usuario + ") cannot be destroyed since the Aluno " + alunoListOrphanCheckAluno + " in its alunoList field has a non-nullable usuario field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Status status = usuario.getStatus();
            if (status != null) {
                status.getUsuarioList().remove(usuario);
                status = em.merge(status);
            }
            Papeis papel = usuario.getPapel();
            if (papel != null) {
                papel.getUsuarioList().remove(usuario);
                papel = em.merge(papel);
            }
            em.remove(usuario);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Usuario> findUsuarioEntities() {
        return findUsuarioEntities(true, -1, -1);
    }

    public List<Usuario> findUsuarioEntities(int maxResults, int firstResult) {
        return findUsuarioEntities(false, maxResults, firstResult);
    }

    private List<Usuario> findUsuarioEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Usuario.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Usuario findUsuario(UsuarioPK id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Usuario.class, id);
        } finally {
            em.close();
        }
    }

    public int getUsuarioCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Usuario> rt = cq.from(Usuario.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
